using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
namespace DAL
{
    public class Threads : DAL.DataManager<Thread>
    {
        private static Threads Instance = new Threads();
        static Threads() { }

        public static string GetTableName()
        {
            return Instance.TableName;
        }

        public override string TableName
        {
            get { return @"yboard_threads"; }
        }

        protected override void CopyToItem(DataRow Row, Thread Item)
        {
            Item.Forum = Forums.Item(Convert.ToInt64(Row["ForumID"]));

            switch (Convert.ToInt32(Row["Priority"]))
            {
                case 1:
                    Item.Priority = Thread.ThreadPriority.Sticky;
                    break;
                default:
                    Item.Priority = Thread.ThreadPriority.Normal;
                    break;
            }


            Item.FirstPost = Posts.Item(Convert.ToInt64(Row["FirstPostID"]));
            Item.LastPost = Posts.Item(Convert.ToInt64(Row["LastPostID"]));
            Item.TotalReplies = Convert.ToInt32(Row["TotalReplies"]);
            Item.TotalViews = Convert.ToInt32(Row["TotalViews"]);

            switch (Convert.ToInt32(Row["Status"]))
            {
                case 0:
                    Item.Status = Thread.ThreadStatus.Locked;
                    break;
                case -1:
                    Item.Status = Thread.ThreadStatus.Deleted;
                    break;
                case 1:
                    Item.Status = Thread.ThreadStatus.Open;
                    break;
            }
        }

        protected override void CopyFromItem(DataManagerQuery query, Thread Item)
        {
            query.AddParam("ForumID", Item.Forum.ID);

            switch (Item.Priority)
            {
                case Thread.ThreadPriority.Sticky:
                    query.AddParam("Priority", 1);
                    break;
                default:
                    query.AddParam("Priority", 0);
                    break;
            }


            query.AddParam("FirstPostID", Item.FirstPost.ID);
            query.AddParam("LastPostID", Item.LastPost.ID);
            query.AddParam("TotalViews", Item.TotalViews);
            query.AddParam("TotalReplies", Item.TotalReplies);

            switch (Item.Status)
            {
                case Thread.ThreadStatus.Locked:
                    query.AddParam("Status", 0);
                    break;
                case Thread.ThreadStatus.Deleted:
                    query.AddParam("Status", -1);
                    break;
                default:
                    query.AddParam("Status", 1);
                    break;
            }
        }

        public static Thread Item(Int64 id)
        {
            return Instance.GetItem(id);
        }

        public static List<Thread> All()
        {
            return Instance.GetItems();
        }

        private static void AddStatusParam(DataManagerQuery query)
        {
            if (Managers.UserLoginManager.CurrentUser == null ||
                Managers.UserLoginManager.CurrentUser.Status != User.UserStatus.Banned)
            {
                query.AddParam("Status", Comparison.GreaterThanOrEqual, 0);
            }
        }

        public static void Add(Thread Item)
        {
            if (Item.Forum == null)
            {
                throw new ThreadNullForumException("Cannot create a new thread without a parent forum.");
            }
            Item.Forum.TotalThreads += 1;
            Item.Forum.TotalPosts += 1;
            Forums.Save(Item.Forum);
            Item.Status = Thread.ThreadStatus.Open;
            Item.Priority = Thread.ThreadPriority.Normal;

            Instance.Insert(Item);
        }

        public static void Save(Thread Item)
        {
            Instance.Update(Item);
        }

        public static List<Thread> GetByForum(Forum parentForum)
        {
            DataManagerQuery query = new DataManagerQuery();
            query.AddParam("ForumID", parentForum.ID);
            query.AddSort("Priority", Sort.Desc);
            query.AddSort("LastPostID", Sort.Desc);
            return Instance.GetItems(query);
        }

        public static DataManagerPage<Thread> GetByForumAndPage(Forum parentForum, int page)
        {
            DataManagerQuery query = new DataManagerQuery();
            query.AddParam("ForumID", parentForum.ID);
            query.AddParam("Priority", 0);
            AddStatusParam(query);
            query.AddSort("LastPostID", Sort.Desc);

            DataManagerPage<Thread> myItems = Instance.GetItemsByPage(query, page, 25);

            if (page == 1)
            {
                List<Thread> threadsWithPriority = GetByForumAndPriority(parentForum, Thread.ThreadPriority.Sticky);

                List<Thread> allThreads = new List<Thread>(myItems.Items.Count + threadsWithPriority.Count);
                allThreads.AddRange(threadsWithPriority);
                allThreads.AddRange(myItems.Items);

                myItems.Items = allThreads;
            }

            return myItems;
        }

        public static List<Thread> GetByForumAndPriority(Forum parentForum, Thread.ThreadPriority priority)
        {
            DataManagerQuery query = new DataManagerQuery();
            query.AddParam("ForumID", parentForum.ID);
            AddStatusParam(query);

            switch (priority)
            {
                case Thread.ThreadPriority.Sticky:
                    query.AddParam("Priority", 1);
                    break;
                default:
                    query.AddParam("Priority", 0);
                    break;
            }

            query.AddSort("LastPostID", Sort.Desc);
            return Instance.GetItems(query);
        }

        public static int GetTotalThreads()
        {
            DataManagerQuery query = new DataManagerQuery();
            AddStatusParam(query);
            return Instance.GetCount(query);
        }

        public static Thread GetLastThreadByForum(Forum parentForum)
        {
            DataManagerQuery query = new DataManagerQuery();
            query.AddParam("ForumID", parentForum.ID);
            AddStatusParam(query);
            query.AddSort("LastPostID", Sort.Desc);

            DataManagerPage<Thread> myThread = Instance.GetItemsByPage(query, 1, 1);
            if (myThread.Items.Count > 0)
            {
                return myThread.Items[0];
            }
            else
            {
                return null;
            }
        }

        public static List<Thread> Search(Helpers.ForumSearchHelper search, int page)
        {
            search.DisplayMode = Helpers.ForumSearchHelper.Display.AsThreads;
            SqlCommand comm = search.GenerateSearchSqlCommand(page);
            return Instance.GetBySqlCommand(comm);
        }
    }

    public class Thread : DAL.DataManagerRow
    {
        public enum ThreadStatus
        {
            Open,
            Locked,
            Deleted
        }

        public enum ThreadPriority
        {
            Normal,
            Sticky
        }

        private Forum _Forum;
        public Forum Forum
        {
            get
            {
                return _Forum;
            }
            set
            {
                _Forum = value;
            }
        }

        private int _totalReplies;
        public int TotalReplies
        {
            get
            {
                return _totalReplies;
            }
            set
            {
                _totalReplies = value;
            }
        }

        public int TotalPages
        {
            get
            {
                return (int)Math.Ceiling((double)((TotalReplies + 1) / 25.0));
            }
        }

        private int _totalViews;
        public int TotalViews
        {
            get
            {
                return _totalViews;
            }
            set
            {
                _totalViews = value;
            }
        }

        private ThreadPriority _Priority;
        public ThreadPriority Priority
        {
            get
            {
                return _Priority;
            }
            set
            {
                _Priority = value;
            }
        }


        private Post _FirstPost;
        public Post FirstPost
        {
            get
            {
                return _FirstPost;
            }
            set
            {
                _FirstPost = value;
            }
        }


        private Post _LastPost;
        public Post LastPost
        {
            get
            {
                return _LastPost;
            }
            set
            {
                _LastPost = value;
            }
        }

        private ThreadStatus _Status;
        public ThreadStatus Status
        {
            get
            {
                return _Status;
            }
            set
            {
                _Status = value;
            }
        }
    }
}